package com.mango.module.ldap.service.impl;

import static org.springframework.ldap.query.LdapQueryBuilder.query;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.query.LdapQuery;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.mango.module.ldap.domain.PersonDO;
import com.mango.module.ldap.mapper.PersonAttributesMapper;
import com.mango.module.ldap.service.IPersonService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service("personService")
public class PersonServiceImpl implements IPersonService {

	@Autowired
	private LdapTemplate ldapTemplate;

	/**
	 * 查询部分字段集合
	 * 
	 * @return
	 */
	@Override
	public List<String> getAllPersonNames() {
		return ldapTemplate.search(query().where("objectclass").is("sperson"),
				(AttributesMapper<String>) attrs -> (String) attrs.get("cn").get());
	}

	@Override
	public List<String> getAllPersonNamesWithTraditionalWay() {
		Hashtable<String, String> env = new Hashtable<>();
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
		env.put(Context.PROVIDER_URL, "ldap://180.209.97.11:389/dc=njupt,dc=edu,dc=cn");
		env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=njupt,dc=edu,dc=cn");
		env.put(Context.SECURITY_CREDENTIALS, "Feng_011509");
		DirContext ctx;
		try {
			ctx = new InitialDirContext(env);
		} catch (NamingException e) {
			throw new RuntimeException(e);
		}

		List<String> list = new LinkedList<String>();
		NamingEnumeration<?> results = null;
		try {
			SearchControls controls = new SearchControls();
			controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
			results = ctx.search("", "(objectclass=sperson)", controls);
			while (results.hasMore()) {
				SearchResult searchResult = (SearchResult) results.next();
				Attributes attributes = searchResult.getAttributes();
				Attribute attr = attributes.get("cn");
				String cn = attr.get().toString();
				list.add(cn);
			}
		} catch (NameNotFoundException e) {
			// The base context was not found.
			// Just clean up and exit.
		} catch (NamingException e) {
			// throw new RuntimeException(e);
		} finally {
			if (results != null) {
				try {
					results.close();
				} catch (Exception e) {
					// Never mind this.
				}
			}
			if (ctx != null) {
				try {
					ctx.close();
				} catch (Exception e) {
					// Never mind this.
				}
			}
		}
		return list;
	}

	@Override
	public List<PersonDO> getAllPersons() {
		return ldapTemplate.search(query().where("objectclass").is("sperson"), new PersonAttributesMapper());
	}

	@Override
	public PersonDO findPersonWithDn(String dn) {
		return ldapTemplate.lookup(dn, new PersonAttributesMapper());
	}

	@Override
	public List<String> getPersonNamesByRoleId(String roleId) {
		LdapQuery query = query().attributes("cn", "sn").where("objectclass").is("sperson").and("roleId").is(roleId);
		return ldapTemplate.search(query, (AttributesMapper<String>) attrs -> (String) attrs.get("cn").get());
	}

	@Override
	public boolean addUser(PersonDO person) {
		try {
			Attributes attrs = buildAttributes(person);
			String ou=StringUtils.isEmpty(person.getOu())?"":",ou="+person.getOu();
			ldapTemplate.bind("uid=" + person.getUserId().trim()+ou, null, attrs);

		} catch (Exception e) {
			log.error("添加人员异常", e);
			return false;
		}
		return true;
	}

	@Override
	public boolean updateUser(PersonDO person) {
		try {
			ModificationItem[] mItems = new ModificationItem[] {
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("ou", person.getOu())),
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
							new BasicAttribute("givenName", person.getGivenName())),
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
							new BasicAttribute("cn", StringUtils.trimToEmpty(person.getName()))),
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
							new BasicAttribute("userPassword", StringUtils.trimToEmpty(person.getUserPassword()))),
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
							new BasicAttribute("roleId", StringUtils.trimToEmpty(person.getRoleId()))),
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
							new BasicAttribute("roleName", StringUtils.trimToEmpty(person.getRoleName()))),
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
							new BasicAttribute("status", StringUtils.trimToEmpty(person.getStatus()))),
					new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
							new BasicAttribute("lastTime", StringUtils.trimToEmpty(person.getLastTime()))) };
			ldapTemplate.modifyAttributes("uid=" + person.getUserId().trim(), mItems);
		} catch (Exception e) {
			log.error("更新人员异常", e);
			return false;
		}
		return true;
	}

	@Override
	public boolean delUser(String uid) {
		try {
			ldapTemplate.unbind("uid=" + uid.trim());

		} catch (Exception e) {
			log.error("删除人员异常", e);
			return false;
		}
		return true;
	}

	private Attributes buildAttributes(PersonDO person) {
		// 基类设置
		BasicAttribute ocattr = new BasicAttribute("objectClass");
		ocattr.add("top");
		ocattr.add("person");
		ocattr.add("sperson");
		// 用户属性
		Attributes attrs = new BasicAttributes();
		attrs.put(ocattr);
		attrs.put("givenName", person.getGivenName());
		attrs.put("uid", StringUtils.trimToEmpty(person.getUserId()));// 显示
		attrs.put("cn", StringUtils.trimToEmpty(person.getName()));
		attrs.put("sn", StringUtils.trimToEmpty(person.getSn()));
		attrs.put("userPassword", StringUtils.trimToEmpty(person.getUserPassword()));
		attrs.put("roleId", StringUtils.trimToEmpty(person.getRoleId()));
		attrs.put("roleName", StringUtils.trimToEmpty(person.getRoleName()));
		attrs.put("zjhm", StringUtils.trimToEmpty(person.getZjhm()));
		attrs.put("lastTime", StringUtils.trimToEmpty(person.getLastTime()));
		attrs.put("status", StringUtils.trimToEmpty(person.getStatus()));
		return attrs;
	}

	@Override
	public PersonDO getPersonByUid(String uid) {
		LdapQuery query = query().where("objectclass").is("sperson").and("uid").is(uid);
		List<PersonDO> list=ldapTemplate.search(query, new PersonAttributesMapper());
		return CollectionUtils.isEmpty(list)? null:list.get(0);
	}

}
